#include "swpentitygraphicitemcontent.h"

#include "graphicitemcommon.h"

#include <ieditoritem.h>

#include <QtCore/QObject>
#include <QtCore/QRegExp>
#include <QtGui/QFontMetrics>
#include <QtGui/QGraphicsSimpleTextItem>
#include <QtGui/QPainter>

using namespace core;
using namespace swp;

SwpEntityGraphicItemContent::SwpEntityGraphicItemContent(
    const QString& entityType,
    const QString& entityName, QGraphicsItem* parent) :
        QGraphicsRectItem(parent), IGraphicItemContent(),
        m_type(entityType),
        m_entity(entityName),
        m_typeItem(0),
        m_entityItem(0),
        m_cropped(false)
{   
    m_typeItem =
        new QGraphicsSimpleTextItem(QString("<<%1>>").arg(entityType), this);

    QFont font = m_typeItem->font();
    font.setBold(true);
    m_typeItem->setFont(font);

    m_entityItem = new QGraphicsSimpleTextItem(m_entity, this);

    const int tWidth = m_typeItem->boundingRect().width();
    const int eWidth = m_entityItem->boundingRect().width();

    reorganize(eWidth, tWidth);

    setPen(QPen(Qt::transparent));
}

SwpEntityGraphicItemContent::~SwpEntityGraphicItemContent()
{

}

void SwpEntityGraphicItemContent::setEntityName(const QString& entityName)
{
    m_entity = entityName;

    refresh();
}

QString SwpEntityGraphicItemContent::entityName() const
{
    return m_entity;
}

QString SwpEntityGraphicItemContent::entityType(
    ) const
{
    return m_type;
}

QGraphicsItem* SwpEntityGraphicItemContent::graphicsItem() const
{
    return const_cast<SwpEntityGraphicItemContent* >(this);
}

void SwpEntityGraphicItemContent::drawThumbnail(QPainter& painter,
    const QRectF& boundingRect)
{
    const qreal coefficient =  qMin(
        boundingRect.width() /
        this->boundingRect().width(),
        boundingRect.height() /
        this->boundingRect().height());

    QTransform transform;
    transform.scale(coefficient, coefficient);
    QRectF transformed = transform.mapRect(this->boundingRect());
    transformed.setX(0);
    transformed.setY(0);

    QRectF _transformed = transformed.translated(
        (boundingRect.width() + (boundingRect.x() * 2) - transformed.width())
            / 2,
        (boundingRect.height() + (boundingRect.y() * 2) -
            transformed.height()) / 2);

    QFont font = m_typeItem->font();

    font.setPointSize(int(font.pointSize() * coefficient));
    font.setBold(true);

    painter.setFont(font);

    painter.drawText(_transformed, Qt::AlignCenter, m_typeItem->text());
}

QRectF SwpEntityGraphicItemContent::croppedBoundingRect() const
{
    const QRectF ret = QGraphicsRectItem::boundingRect();

    return ret;
}

void SwpEntityGraphicItemContent::recheckIfFits()
{
    const int pWidth = parentItem()->boundingRect().width() -
        (2 * PREFERRED_CONTENT_PADDING);

    QFontMetrics metrics(m_entityItem->font());

    const int width = metrics.width(m_entity);

    if (width <= pWidth)
    {
        m_entityItem->setText(m_entity);

        const int tWidth = m_typeItem->boundingRect().width();
        const int eWidth = m_entityItem->boundingRect().width();

        reorganize(eWidth, tWidth);

        m_cropped = false;
    }
    else
    {
        QFontMetrics metrics(m_entityItem->font());

        const QString elided = metrics.elidedText(
            m_entity, Qt::ElideRight, pWidth);

        m_entityItem->setText(elided);

        const int tWidth = m_typeItem->boundingRect().width();
        const int eWidth = m_entityItem->boundingRect().width();

        reorganize(eWidth, tWidth);

        m_cropped = true;
    }
}

void SwpEntityGraphicItemContent::setPalette(const Palette* const palette)
{

}

bool SwpEntityGraphicItemContent::doActionForProperty(
    const QString& property, const QVariantList& value,
    const core::SerializationEngine& helper)
{
    if (property == "type")
    {
        m_type = value.first().toString();
    }
    else if (property == "entity")
    {
        m_entity = value.first().toString();
    }

    return true;
}

void SwpEntityGraphicItemContent::deserializationFinished(bool ok)
{
    if (ok)
    {
        refresh();
    }
}

QHash<QString, QVariantList> SwpEntityGraphicItemContent::serializationData(
    const core::SerializationEngine& helper) const
{
    QHash<QString, QVariantList> ret;

    QVariantList list;
    list.append(QVariant(m_type));

    ret["type"] = list;

    list.clear();

    list.append(QVariant(m_entity));

    ret["entity"] = list;

    return ret;
}

QRectF SwpEntityGraphicItemContent::boundingRect() const
{
    QRectF ret = QGraphicsRectItem::boundingRect();

    if (m_cropped)
    {
        QFontMetrics metrics(m_entityItem->font());

        const int width = metrics.width(m_entity) +
            (2 * PREFERRED_CONTENT_PADDING);

        ret.setWidth(width);
    }

    return ret;
}

void SwpEntityGraphicItemContent::refresh()
{
    m_typeItem->setText(QString("<<%1>>").arg(m_type));

    m_entityItem->setText(m_entity);

    const int tWidth = m_typeItem->boundingRect().width();
    int eWidth = m_entityItem->boundingRect().width();

    const int pWidth = parentItem()->boundingRect().width() -
        (2 * PREFERRED_CONTENT_PADDING);

    if (eWidth > pWidth)
    {
        QFontMetrics metrics(m_entityItem->font());

        const QString elided = metrics.elidedText(
            m_entity, Qt::ElideRight, pWidth);

        m_entityItem->setText(elided);

        eWidth = pWidth;

        m_cropped = true;
    }
    else
    {
        m_cropped = false;
    }

    reorganize(eWidth, tWidth);
}

void SwpEntityGraphicItemContent::relayout()
{
    const QRectF childrenRect = childrenBoundingRect();

    setRect(QRectF(0, 0,
        childrenRect.width() + PREFERRED_CONTENT_PADDING * 2,
        childrenRect.height() + PREFERRED_CONTENT_PADDING * 2));
}

void SwpEntityGraphicItemContent::reorganize(int eWidth, int tWidth,
    bool refresh)
{
    const qreal tX = tWidth > eWidth ?
        PREFERRED_CONTENT_PADDING :
            (PREFERRED_CONTENT_PADDING + (eWidth - tWidth) / 2);
    const qreal eX = eWidth > tWidth ?
        PREFERRED_CONTENT_PADDING :
            (PREFERRED_CONTENT_PADDING + (tWidth - eWidth) / 2);

    m_typeItem->setPos(tX,
        PREFERRED_CONTENT_PADDING);
    m_entityItem->setPos(eX,
        m_typeItem->boundingRect().height() + PREFERRED_CONTENT_ITEM_SPACING);

    IGraphicEditorItem* parent = dynamic_cast<IGraphicEditorItem*>(
        parentItem());

    Q_ASSERT(parent != 0); // can't be null

    relayout();

    if (refresh)
    {
        parent->handleContentRefresh();
    }
}
